/*
Pyxis 2.0
Copyright 2010-2011 Thomas W. Holtquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using System;
using System.Collections;
using System.Ext.Xml;
using System.Net;
using System.IO;
using System.Threading;
using System.Text;
using System.Xml;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Net.NetworkInformation;

using GHIElectronics.NETMF.System;

using Skewworks.Pyxis.EXT;
using Skewworks.Pyxis.GUI;
using Skewworks.Pyxis.GUI.Controls;

namespace Skewworks.Pyxis.Kernel
{

    internal class Desktop : Container
    {

        #region Variables

        private PyxisAPI API;                                   // Reference to PyxisAPI

        internal Color _bkgColor = Colors.LightGray;            // Background Color
        internal Bitmap _bkgImage = null;                       // Background Image
        private ScaleMode _bkgScale = ScaleMode.Normal;         // Background Image Scaling

        private bool _appstore;                                 // Display App Store Icon
        private bool _filefinder;                               // Display File Finder Icon
        private bool _pictureviewer;                            // Display Picture Viewer Icon
        private bool _settings;                                 // Display Settings Icon

        internal MenuBar _mnu;                                  // System MenuBar
        private MenuItem mnuDesktop;                            // Desktop Menu
        internal MenuItem mnuRun;                               // Pyxis Run Menu Item
        internal MenuItem mnuForce;                             // Pyxis Force Quit Menu Item
        private MenuItem mnuDSep;                               // Desktop separator
        private MenuItem mnuPage;                               // Desktop page select

        private ArrayList _icons = new ArrayList();             // Array of Icons waiting to be rendered to the buffer
        private Bitmap _icoBuffer = null;                       // Buffer of Icon images used to speed up rendering

        private int _hSpacing;                                  // Horizontal Icon Spacing
        private int _vSpacing;                                  // Vertical Icon Spacing
        private int _pages;                                     // # of Desktop Pages needed
        private int _curPage;                                   // Current Desktop Page
        private int _IPP;                                       // Icons Per Page

        private DesktopIcon _ActiveIcon;                        // Actively selected icon
        private ContextMenu _IconCM;                            // Icon ContextMenu

        #endregion

        #region Constructor

        public Desktop(PyxisAPI api)
        {
            // Hook Events
            api.MyDrives.DriveAdded += new OnDriveAdded(MyDrives_DriveAdded);
            api.MyDrives.DriveRemoved += new OnDriveRemoved(MyDrives_DriveRemoved);

            // Copy out API
            API = api;

            // Calculate Icon Spacing
            int IPR = (int)System.Math.Floor(AppearanceManager.ScreenWidth / 80);
            _hSpacing = (int)System.Math.Floor((AppearanceManager.ScreenWidth - (IPR * 80)) / (IPR + 1));
            int IPC = (int)System.Math.Floor((AppearanceManager.ScreenHeight - 24) / 74);
            _vSpacing = (int)System.Math.Floor(((AppearanceManager.ScreenHeight - 24) - (IPC * 74)) / (IPC + 1));
            _IPP = IPR * IPC;

            // Prep Desktop
            CreateMenus();
            DetectPrimaryHDD();
            if (SettingsManager.BootSettings.CheckUpdates)
                API.CheckForUpdates(true);
        }

        #endregion

        #region Properties

        public override Bitmap ScreenBuffer
        {
            get
            {
                return API.ScreenBuffer;
            }
        }

        #endregion

        #region GUI

        public override void Render(bool bFullRender = false)
        {
            // Only set the clip region if we're not the top form AND we're not doing a full render
            if (API.ActiveForm != null && !bFullRender) 
                API.ScreenBuffer.SetClippingRectangle(0, 0, AppearanceManager.ScreenWidth, 22);

            // Render the background
            RenderBkg(API.ScreenBuffer);

            // Remove any clipping region
            API.ScreenBuffer.SetClippingRectangle(0, 0, AppearanceManager.ScreenWidth, AppearanceManager.ScreenHeight);

            if (API._ActiveForm == null)
            {
                // Draw icons if there's no active form
                DrawIcons();
            }
            else if (bFullRender)
                API.ActiveForm.Render(false);

            // Render the menu
            if (_mnu != null) 
                _mnu.Render();

            // Flush the buffer
            API.ScreenBuffer.Flush();
        }

        internal void RenderBkg(Bitmap target)
        {
            // Fill with solid background first
            target.DrawRectangle(_bkgColor, 1, 0, 0, AppearanceManager.ScreenWidth, AppearanceManager.ScreenHeight, 0, 0, _bkgColor, 0, 0, _bkgColor, 0, 0, 256);

            // Exit if no image
            if (_bkgImage == null)
                return;

            // Draw image by scale
            int dsW, dsH, dX, dY;
            switch (_bkgScale)
            {
                case ScaleMode.Center:
                    dX = AppearanceManager.ScreenWidth / 2 - _bkgImage.Width / 2;
                    dY = AppearanceManager.ScreenHeight / 2 - _bkgImage.Height / 2;
                    target.DrawImage(dX, dY, _bkgImage, 0, 0, _bkgImage.Width, _bkgImage.Height);
                    break;
                case ScaleMode.Normal:
                    target.DrawImage(0, 0, _bkgImage, 0, 0, _bkgImage.Width, _bkgImage.Height);
                    break;
                case ScaleMode.Scale:
                    float multiplier;
                    int dH = AppearanceManager.ScreenHeight;
                    int dW = AppearanceManager.ScreenWidth;


                    if (_bkgImage.Height > _bkgImage.Width)
                    {
                        // Portrait
                        if (dH > dW)
                        {
                            multiplier = (float)dW / (float)_bkgImage.Width;
                        }
                        else
                        {
                            multiplier = (float)dH / (float)_bkgImage.Height;
                        }
                    }
                    else
                    {
                        // Landscape
                        if (dH > dW)
                        {
                            multiplier = (float)dW / (float)_bkgImage.Width;
                        }
                        else
                        {
                            multiplier = (float)dH / (float)_bkgImage.Height;
                        }
                    }

                    dsW = (int)((float)_bkgImage.Width * multiplier);
                    dsH = (int)((float)_bkgImage.Height * multiplier);
                    dX = (int)((float)dW / 2 - (float)dsW / 2);
                    dY = (int)((float)dH / 2 - (float)dsH / 2);

                    target.DrawImage(dX, dY, _bkgImage, 0, 0, dsW, dsH);
                    break;
                case ScaleMode.Stretch:
                    target.DrawImage(0, 0, _bkgImage, 0, 0, AppearanceManager.ScreenWidth, AppearanceManager.ScreenHeight);
                    break;
                case ScaleMode.Tile:
                    for (dX = 0; dX < AppearanceManager.ScreenWidth; dX += _bkgImage.Width)
                    {
                        for (dY = 0; dY < target.Height; dY += _bkgImage.Height)
                            target.DrawImage(dX, dY, _bkgImage, 0, 0, _bkgImage.Width, _bkgImage.Height);
                    }
                    break;
            }
        }

        private void DrawIcons()
        {
            if (_icons.Count == 0) return;

            if (_icoBuffer == null)
            {
                for (int i = 0; i < _icons.Count; i++)
                {
                    DesktopIcon di = (DesktopIcon)_icons[i];
                    di.Render();
                    di.Image = null;    // Clear image to free memory; it's in buffer anyway
                }

                _icoBuffer = new Bitmap(AppearanceManager.ScreenWidth, AppearanceManager.ScreenHeight - 22);
                _icoBuffer.DrawImage(0, 0, API.ScreenBuffer, 0, 22, _icoBuffer.Width, _icoBuffer.Height);
            }
            else
            {
                API.ScreenBuffer.DrawImage(0, 22, _icoBuffer, 0, 0, _icoBuffer.Width, _icoBuffer.Height);
            }
        }

        #endregion

        #region Public Methods

        public void Activate()
        {
            if (_mnu.count < 2)
            {
                _mnu.add(mnuDesktop);
            }
            else
            {
                if (_mnu.GetItemAt(1) != mnuDesktop)
                {
                    _mnu.remove(1);
                    _mnu.add(mnuDesktop);
                }
            }

            if (API.MyDrives.RootDirectory != "\\") 
                LoadDesktopIcons();

            Render();
        }

        #endregion

        #region Internal Methods

        /// <summary>
        /// Updates the desktop.xml settings file
        /// </summary>
        /// <param name="BkgImage"></param>
        /// <param name="BkgColor"></param>
        /// <param name="BkgScale"></param>
        /// <param name="ShowAppStore"></param>
        /// <param name="ShowFileFinder"></param>
        /// <param name="ShowPictureViewer"></param>
        /// <param name="ShowSetthings"></param>
        internal void UpdateSettings(string BkgImage, Color BkgColor, int BkgScale, bool ShowAppStore, bool ShowFileFinder, bool ShowPictureViewer, bool ShowSetthings)
        {

            // Update local variables
            try
            {
                _appstore = ShowAppStore;
                _filefinder = ShowFileFinder;
                _pictureviewer = ShowPictureViewer;
                _settings = ShowSetthings;
                _bkgColor = BkgColor;
                _bkgScale = (ScaleMode)BkgScale;
                _bkgImage = PyxisAPI.ImageFromBytes(File.ReadAllBytes(BkgImage));
            }
            catch (Exception) { }

            // Create Desktop XML
            if (API.MyDrives.RootDirectory != "\\")
            {
                string sName = API.MyDrives.RootDirectory + "pyxis\\system\\desktop.xml";
                if (File.Exists(sName)) File.Delete(sName);
                FileStream iFile = new FileStream(sName, FileMode.CreateNew);
                XmlWriter xmlwrite = XmlWriter.Create(iFile);
                xmlwrite.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
                xmlwrite.WriteComment("Pyxis 2.0 Desktop Settings");
                xmlwrite.WriteStartElement("Settings");

                xmlwrite.WriteStartElement("Appearance");

                xmlwrite.WriteStartElement("Backcolor");
                xmlwrite.WriteString(ColorUtility.GetRValue(_bkgColor) + "," + ColorUtility.GetGValue(_bkgColor) + "," + ColorUtility.GetBValue(_bkgColor));
                xmlwrite.WriteEndElement();

                xmlwrite.WriteStartElement("Wallpaper");
                xmlwrite.WriteString(PyxisAPI.StringReplace(BkgImage, API.MyDrives.RootDirectory + "pxyis\\wallpapers\\", ""));
                xmlwrite.WriteEndElement();

                xmlwrite.WriteStartElement("WallpaperMode");
                xmlwrite.WriteString(_bkgScale.ToString());
                xmlwrite.WriteEndElement();

                xmlwrite.WriteStartElement("ShowAppStore");
                xmlwrite.WriteString((_appstore) ? "1" : "0");
                xmlwrite.WriteEndElement();

                xmlwrite.WriteStartElement("ShowFileFinder");
                xmlwrite.WriteString((_filefinder) ? "1" : "0");
                xmlwrite.WriteEndElement();

                xmlwrite.WriteStartElement("ShowPictureViewer");
                xmlwrite.WriteString((_pictureviewer) ? "1" : "0");
                xmlwrite.WriteEndElement();

                xmlwrite.WriteStartElement("ShowSettings");
                xmlwrite.WriteString((_settings) ? "1" : "0");
                xmlwrite.WriteEndElement();

                xmlwrite.WriteEndElement();

                xmlwrite.WriteEndElement();
                xmlwrite.Flush();
                xmlwrite.Close();
                iFile.Close();
                API.MyDrives.FlushFileSystems();
            }

            _mnu._buffer = null;
            Render(true);
        }

        #endregion

        #region Private Methods

        private void CreateMenus()
        {
            // SYSTEM MENU
            _mnu = new MenuBar(this, API, (DeviceManager.ActiveDevice == DeviceType.ChipworkX) ? true : false);
            _mnu.Suspended = true;

            MenuItem mnuMain = new MenuItem(PyxisAPI.Product);

            MenuItem mnuAbout = new MenuItem("About " + PyxisAPI.Product);
            mnuAbout.tapEvent += new MenuItemTap((object sender) => API.ShowAbout());
            mnuMain.AddItem(mnuAbout);

            MenuItem mnuUpdate = new MenuItem("Software Update");
            mnuUpdate.tapEvent += new MenuItemTap((object sender) => API.CheckForUpdates(false));
            mnuMain.AddItem(mnuUpdate);

            MenuItem mnusSepApps = new MenuItem("-");
            mnuMain.AddItem(mnusSepApps);

            if (DeviceManager.ActiveDevice == DeviceType.ChipworkX)
            {
                MenuItem mnuMount = new MenuItem((API.MyDrives.SDMounted) ? "Unmount SD" : "Mount SD");
                mnuMount.tapEvent += new MenuItemTap((object sender) => SDHandler(mnuMount));
                mnuMain.AddItem(mnuMount);
            }

            MenuItem mnuSysTools = new MenuItem("System Tools");

            MenuItem mnuAS = new MenuItem("App Market");
            mnuAS.tapEvent += new MenuItemTap((object sender) => AppStore.Show(API));
            mnuSysTools.AddItem(mnuAS);

            MenuItem mnuFF = new MenuItem("File Finder");
            mnuFF.tapEvent += new MenuItemTap((object sender) => FileFinder.Show(API));
            mnuSysTools.AddItem(mnuFF);

            MenuItem mnuPV = new MenuItem("Picture Viewer");
            mnuPV.tapEvent += new MenuItemTap((object sender) => PictureViewer.Show(API, null));
            mnuSysTools.AddItem(mnuPV);

            MenuItem mnuSettings = new MenuItem("Settings");
            mnuSettings.tapEvent += new MenuItemTap((object sender) => SettingsWin.Show(API));
            mnuSysTools.AddItem(mnuSettings);

            mnuSysTools.AddItem(new MenuItem("-"));

            MenuItem mnuCalibrate = new MenuItem("Calibrate LCD");
            mnuCalibrate.tapEvent += new MenuItemTap((object sender) => API.CalibrateScreen());
            mnuSysTools.AddItem(mnuCalibrate);

            MenuItem mnuDesk = new MenuItem("Show Desktop");
            mnuDesk.tapEvent += new MenuItemTap((object target) => API.DisplayDesktop());
            mnuMain.AddItem(mnuDesk);

            mnuMain.AddItem(mnuSysTools);
            mnuMain.AddItem(new MenuItem("-"));

            mnuRun = new MenuItem("Switch To");
            mnuRun.Enabled = false;
            mnuMain.AddItem(mnuRun);

            mnuForce = new MenuItem("Force Quit");
            mnuForce.Enabled = false;
            mnuMain.AddItem(mnuForce);

            _mnu.add(mnuMain);
            _mnu.Suspended = false;
            _mnu._buffer = null;

            // DESKTOP MENU
            mnuDesktop = new MenuItem("Desktop");
            MenuItem mnuRefresh = new MenuItem("Refresh");
            mnuRefresh.tapEvent += new MenuItemTap((object sender) => LoadDesktopIcons());
            mnuDesktop.AddItem(mnuRefresh);
            mnuDSep = new MenuItem("-");
            mnuDSep.Visible = false;
            mnuPage = new MenuItem("Show Page");
            mnuPage.Visible = false;
            mnuDesktop.AddItem(mnuDSep);
            mnuDesktop.AddItem(mnuPage);

            _mnu.add(mnuMain);

            // ICON CONTEXT MENU
            ContextMenuItem cmiOpen = new ContextMenuItem("Run");
            cmiOpen.tapEvent += new GUI.Controls.MenuItemTap(RunIcon);
            
            ContextMenuItem cmiSep = new ContextMenuItem("-");
            
            ContextMenuItem cmiRename = new ContextMenuItem("Rename");
            
            ContextMenuItem cmiDelete = new ContextMenuItem("Delete");
            cmiDelete.tapEvent += new GUI.Controls.MenuItemTap(DeleteIcon);

            _IconCM = new ContextMenu(new ContextMenuItem[] { cmiOpen, cmiSep, cmiRename, cmiDelete });
        }

        private void DetectPrimaryHDD()
        {
            bool needsLoad = (API.MyDrives.RootDirectory == "\\") ? true : false;

            PyxisDrive[] drives = API.MyDrives.AvailableDrives;

            for (int i = 0; i < drives.Length; i++)
            {
                if (IsOSInstalled(drives[i].RootName + "\\"))
                {
                    API.MyDrives.RootDirectory = FileManager.NormalizeDirectory(drives[i].RootName);
                    if (needsLoad)
                    {
                        if (File.Exists(API.MyDrives.RootDirectory + "bootloaderdemand.txt"))
                            SystemUpdate.AccessBootloader();
                        LoadDefaultDrive();
                    }
                    return;
                }
            }

            if (needsLoad)
            {
                if (drives.Length > 0)
                {
                    if (API.Prompt("You have " + drives.Length + " drives available.\nWould you like to prepare a drive for Pyxis?", "Question", PromptType.YesNo) == PromptResult.Yes)
                    {
                        if (drives.Length == 1)
                        {
                            if (API.PrepHDD(API.MyDrives.AvailableDrives[0]))
                            {
                                DetectPrimaryHDD();
                                Render();
                                return;
                            }
                            else
                            {
                                API.Prompt("Could not prepare HDD.\nMake sure there is sufficient room and the drive is not write protected.", "Error", PromptType.OKOnly);
                            }
                        }
                        else
                        {
                            string myDrive = API.SelectDrive();
                            int index = -1;
                            for (int i = 0; i < API.MyDrives.DriveRoots.Length; i++)
                            {
                                if (API.MyDrives.DriveRoots[i] + "\\" == myDrive)
                                {
                                    index = i;
                                    break;
                                }
                            }

                            if (API.PrepHDD(API.MyDrives.AvailableDrives[0]))
                            {
                                DetectPrimaryHDD();
                                Render();
                                return;
                            }
                            else
                            {
                                API.Prompt("Could not prepare HDD.\nMake sure there is sufficient room and the drive is not write protected.", "Error", PromptType.OKOnly);
                            }

                        }
                    }
                }
                LoadDefaultDrive();
            }
        }

        private void LoadDefaultDrive()
        {

            API.MyFiles.LoadAssociations();

            if (API.MyDrives.RootDirectory == "\\")
            {
                // Set Default Desktop
                _bkgImage = new Bitmap(EmbeddedResourceManager.GetWallpaperByName("greenstripes"), Bitmap.BitmapImageType.Jpeg);
                LoadDesktopIcons();

                // Update Menu Items
                //mnuSwitch.Enabled = false;
                mnuRun.Enabled = false;
                mnuForce.Enabled = false;
            }
            else
            {
                LoadDesktopSettings();
                LoadDesktopIcons();

                //mnuSwitch.Enabled = true;
            }
        }

        private void LoadDesktopIcons()
        {
            int x = _hSpacing;
            int y = 24 + _vSpacing;
            bool bVisible = true;
            MenuItem mnu;
            DesktopIcon DI;

            _icoBuffer = null;
            _icons.Clear();
            mnuPage.ClearItems();
            mnuPage.Visible = false;
            mnuDSep.Visible = false;
            mnu = new MenuItem("Page 1");
            mnu.tapEvent += new MenuItemTap((object sender) => LoadDesktopPage(1));
            mnuPage.AddItem(mnu);
            _curPage = 1;
            _pages = 1;

            // App Store Icon
            if (_appstore)
            {
                DI = new DesktopIcon(API, "App Market", "-1", EmbeddedResourceManager.GetImage32BytesByName("AppStore"), x, y, 76, 69, true);
                _icons.Add(DI);
                x += _hSpacing + 80;
            }

            // File Finder Icon
            if (_filefinder)
            {
                DI = new DesktopIcon(API, "File Finder", "-2", EmbeddedResourceManager.GetImage32BytesByName("FileFinder"), x, y, 76, 69, true);
                _icons.Add(DI);
                x += _hSpacing + 80;
            }

            // Picture Viewer Icon
            if (_pictureviewer)
            {
                DI = new DesktopIcon(API, "Picture Viewer", "-3", EmbeddedResourceManager.GetImage32BytesByName("PictureViewer"), x, y, 76, 69, true);
                _icons.Add(DI);
                x += _hSpacing + 80;
            }

            // Settings Icon
            if (_settings)
            {
                DI = new DesktopIcon(API, "Settings", "-4", EmbeddedResourceManager.GetImage32BytesByName("Settings"), x, y, 76, 69, true);
                _icons.Add(DI);
                x += _hSpacing + 80;
            }

            // Check overflow
            if (x + 78 >= AppearanceManager.ScreenWidth)
            {
                x = _hSpacing;
                y += 74 + _vSpacing;
            }

            if (API.MyDrives.RootDirectory != "\\")
            {
                string[] Files = Directory.GetFiles(API.MyDrives.RootDirectory + "pyxis\\desktop\\");
                for (int j = 0; j < Files.Length; j++)
                {
                    if (Path.GetExtension(Files[j]).ToLower() == ".lnk")
                    {
                        try
                        {
                            DI = new DesktopIcon(API, Files[j], x, y, 76, 69, bVisible);
                            DI.TapHold += new OnTapHold(IconTapHold);
                            _icons.Add(DI);
                            x += _hSpacing + 80;
                            if (x + 78 >= AppearanceManager.ScreenWidth)
                            {
                                x = _hSpacing;
                                y += 74 + _vSpacing;
                                if (y + 74 + _vSpacing >= AppearanceManager.ScreenHeight)
                                {
                                    bVisible = false;
                                    x = _hSpacing;
                                    y = 24 + _vSpacing;

                                    _pages++;
                                    mnu = new MenuItem("Page " + _pages);
                                    mnu.tapEvent += new MenuItemTap((object sender) => LoadDesktopPage(_pages));
                                    mnuPage.Visible = true;
                                    mnuDSep.Visible = true;
                                    mnuPage.AddItem(mnu);

                                }
                            }
                        }
                        catch (Exception)
                        { }

                    }
                }
            }

        }

        private void LoadDesktopPage(int index)
        {
            int startIndex = (_curPage - 1) * _IPP;
            int i;
            DesktopIcon DI;

            // We're already here
            if (index == _curPage) return;

            // Hide Current Page
            for (i = startIndex; i < startIndex + _IPP; i++)
            {
                DI = (DesktopIcon)_icons[i];
                DI.Visible = false;
                if (i == _icons.Count - 1) break;
            }

            // Show New Page
            startIndex = (index - 1) * _IPP;
            for (i = startIndex; i < startIndex + _IPP; i++)
            {
                DI = (DesktopIcon)_icons[i];
                DI.Visible = true;
                if (i == _icons.Count - 1) break;
            }

            // Update Buffer
            _curPage = index;
            _icoBuffer = null;
            Render(true);

        }

        private void LoadDesktopSettings()
        {
            API.ScreenBuffer.DrawRectangle(Colors.Black, 1, 0, 0, AppearanceManager.ScreenWidth, AppearanceManager.ScreenHeight, 0, 0, Colors.Black, 0, 0, Colors.Black, 0, 0, 256);
            int tY = (AppearanceManager.ScreenHeight / 2) - (FontManager.ArialBold.Height / 2);
            API.ScreenBuffer.DrawTextInRect("...Loading Desktop...", 0, tY, AppearanceManager.ScreenWidth, FontManager.ArialBold.Height, Bitmap.DT_AlignmentCenter, Colors.White, FontManager.ArialBold);
            API.ScreenBuffer.Flush();

            _mnu._buffer = null;
            _icoBuffer = null;


            // Read system settings
            XMLReaderEX xr = new XMLReaderEX(API.MyDrives.RootDirectory + "\\pyxis\\system\\desktop.Xml");
            XMLNodeEX node = (XMLNodeEX)xr.Nodes[0];
            node = node.NodeByName("Appearance");
            string sPaper = node.NodeByName("Wallpaper").value;
            if (sPaper.IndexOf("\\") < 0) sPaper = API.MyDrives.RootDirectory + "pyxis\\wallpapers\\" + sPaper;
            _appstore = (node.NodeByName("ShowAppStore").value == "1") ? true : false;
            _filefinder = (node.NodeByName("ShowFileFinder").value == "1") ? true : false;
            _settings = (node.NodeByName("ShowSettings").value == "1") ? true : false;
            _pictureviewer = (node.NodeByName("ShowPictureViewer").value == "1") ? true : false;
            string[] vals = node.NodeByName("Backcolor").value.Split(',');
            _bkgColor = ColorUtility.ColorFromRGB(byte.Parse(vals[0]), byte.Parse(vals[1]), byte.Parse(vals[2]));
            _bkgScale = (Skewworks.Pyxis.ScaleMode)(int.Parse(node.NodeByName("WallpaperMode").value));

            // Set wallpaper
            try
            {
                if (sPaper.IndexOf("\\") < 0) sPaper = API.MyDrives.RootDirectory + "\\pyxis\\wallpapers\\" + sPaper;
                FileStream iFile = new FileStream(sPaper, FileMode.Open);
                byte[] b = new byte[iFile.Length];
                iFile.Read(b, 0, b.Length);
                iFile.Close();
                _bkgImage = PyxisAPI.ImageFromBytes(b);
            }
            catch (Exception) { }

            Render();
        }

        private bool IsOSInstalled(string DeviceRoot)
        {

            // Check Directories
            string[] paths = new string[] { "apps\\", "documents\\", "documents\\temp\\", "pictures\\", "pyxis\\", "pyxis\\desktop\\", "pyxis\\fonts", "pyxis\\wallpapers\\", "pyxis\\system\\" };
            for (int i = 0; i < paths.Length; i++) if (!Directory.Exists(DeviceRoot + paths[i])) return false;

            // Check Files
            string[] files = new string[] { "pyxis\\system\\desktop.Xml" };
            for (int i = 0; i < files.Length; i++) if (!File.Exists(DeviceRoot + files[i])) return false;

            // We're good
            return true;
        }

        private void SDHandler(MenuItem mnuMount)
        {
            if (API.MyDrives.SDMounted)
            {
                API.MyDrives.UnmountSD();
                mnuMount.Text = "Mount SD";
            }
            else
            {
                if (API.MyDrives.MountSD())
                {
                    mnuMount.Text = "Unmount SD";
                }
                else
                {
                    API.Prompt("Could not mount SD", PyxisAPI.Product, PromptType.OKOnly);
                }
            }
        }

        #endregion

        #region Touch Methods

        public override void TouchDown(object sender, point e)
        {
            if (API.ActiveForm != null) return;

            // Check Icons
            for (int i = _icons.Count - 1; i >= 0; i--)
            {
                DesktopIcon child = (DesktopIcon)_icons[i];
                if (child.ScreenBounds.contains(e) && child.Visible)
                {
                    child.TouchDown(sender, e);
                    return;
                }

            }

        }

        public override void TouchUp(object sender, point e)
        {
            if (API.ActiveForm != null) return;

            bool ignoreUp = false;

            // Check Icons
            DesktopIcon myControl = null;
            for (int i = _icons.Count - 1; i >= 0; i--)
            {
                myControl = (DesktopIcon)_icons[i];
                if (myControl.ScreenBounds.contains(e) && !ignoreUp && myControl.Visible)
                {
                    myControl.TouchUp(sender, e);
                    ignoreUp = true;
                }
                else if (myControl.PenDown)
                {
                    myControl.TouchUp(sender, e);
                }
            }

        }

        #endregion

        #region Drive Events

        /// <summary>
        /// Handle drives being added
        /// </summary>
        /// <param name="root">Root of new drive</param>
        private void MyDrives_DriveAdded(string root)
        {

            if (API.MyDrives.RootDirectory == "\\")
            {
                DetectPrimaryHDD();
                Render();
            }
        }

        /// <summary>
        /// Handle removal of drives
        /// </summary>
        /// <param name="root">Root of drive removed</param>
        private void MyDrives_DriveRemoved(string root)
        {
            if (API.MyDrives.RootDirectory == root)
            {
                API.MyDrives.RootDirectory = "\\";
                DetectPrimaryHDD();
                Render();
            }
        }

        #endregion

        #region Icon Events

        private void IconTapHold(object sender, point e)
        {
            _ActiveIcon = (DesktopIcon)sender;
            API.ShowContextMenu(_IconCM, e);
        }

        private void RunIcon(object sender)
        {
            API.StartApplication(_ActiveIcon.Target, _ActiveIcon.Title, null);
        }

        private void RenameIcon(object sender)
        {
            // Not yet supported
        }

        private void DeleteIcon(object sender)
        {
            if (API.Prompt("Are you sure you wish to remove '" + _ActiveIcon.Title + "' from the desktop?", PyxisAPI.Product, PromptType.YesNo) == PromptResult.No)
                return;

            try
            {
                File.Delete(_ActiveIcon.Filename);
                API.MyDrives.FlushFileSystems();
                _icons.Remove(_ActiveIcon);
                _ActiveIcon = null;
                _icoBuffer = null;
                LoadDesktopIcons();
                Render(true);
            }
            catch (Exception e)
            {
                API.Prompt("Could not delete '" + _ActiveIcon.Title + "'\n" + e.Message, PyxisAPI.Product, PromptType.OKOnly);
            }

        }

        #endregion

    }

}
